package com.molichuxing.services.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.LocationUtils;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.services.business.dto.request.create.StoreBizCreateDto;
import com.molichuxing.services.business.dto.request.modify.StoreBizModifyDto;
import com.molichuxing.services.business.dto.response.DealerStoreInfoBizDto;
import com.molichuxing.services.business.dto.response.StoreBaseBizDto;
import com.molichuxing.services.business.dto.response.StoreBizDto;
import com.molichuxing.services.business.dto.response.StoreInfoBizDto;
import com.molichuxing.services.business.service.StoreBizService;
import com.molichuxing.services.infrastructure.convertor.Convert;
import com.molichuxing.services.infrastructure.dto.request.create.StoreCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.StoreDetailCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.StoreDetailModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.StoreModifyDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 门店组合 服务实现类
 * </p>
 *
 * @author zph
 * @since 2019-08-12
 */
@Service("storeBizService")
public class StoreBizServiceImpl implements StoreBizService {

    @Autowired
    private StoreService storeService;
    @Autowired
    private StoreDetailService storeDetailService;
    @Autowired
    private DealerService dealerService;
    @Autowired
    private StoreDeviceService storeDeviceService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private FenceStoreStockService fenceStoreStockService;

    @Value("${store.contact.phone}")
    private String STORE_CONTACT_PHONE;

    /**
     * 获取经销商信息分页列表
     *
     * @param map      key:dealerId Integer 经销商id
     *                 key:status Integer 营业状态
     *                 key:verifyStatus Integer 审核状态
     *                 key:shortName String 门店名称
     *                 key：regionId Integer 区域ID
     *                 key:startApplyTime LocalDateTime 申请开始时间
     *                 key:endApplyTime LocalDateTime 申请结束时间
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Paged<StoreBizDto> getStorePage(Map<String, Object> map, Integer pageNum, Integer pageSize) throws Exception {
        Paged<StoreDto> storePage = storeService.getStorePage(map, pageNum, pageSize);
        if (null == storePage) {
            return new Paged<StoreBizDto>();
        }
        List<StoreDto> storeBeanDtoList = storePage.getList();
        if (null == storeBeanDtoList || storeBeanDtoList.size() == 0) {
            return new Paged<StoreBizDto>();
        }

        List<Integer> storeIdList = new ArrayList<>();
        List<Integer> dealerIdList = new ArrayList<>();
        for (StoreDto storeDto : storeBeanDtoList) {
            storeIdList.add(storeDto.getStoreId());
            dealerIdList.add(storeDto.getDealerId());
        }
        Map<Integer, StoreDetailDto> storeDetailDtoMap = storeDetailService.getStoreDetailMapByIds(storeIdList);
        Map<Integer, DealerDto> dealerDtoMap = dealerService.getDealerMapByIds(dealerIdList);
        Map<Integer, Integer> fenceCountMap = fenceStoreStockService.getFenceCount(storeIdList, FenceStoreStockTypeEnum.STORE.getValue());

        List<StoreBizDto> pagedReturnList = getPagedReturnList(storeBeanDtoList, storeDetailDtoMap, dealerDtoMap, fenceCountMap);
        return new Paged<StoreBizDto>(pagedReturnList, storePage.getTotal(), pageSize);
    }

    /**
     * 分页返回list
     *
     * @param storeBeanDtoList
     * @param storeDetailDtoMap
     * @return
     * @throws Exception
     */
    private List<StoreBizDto> getPagedReturnList(List<StoreDto> storeBeanDtoList,
                                                 Map<Integer, StoreDetailDto> storeDetailDtoMap, Map<Integer, DealerDto> dealerDtoMap,
                                                 Map<Integer, Integer> fenceCountMap) throws Exception {
        List<StoreBizDto> storeBizDtoList = Convert.toStoreBizDtoList(storeBeanDtoList);
        for (StoreBizDto storeBizDto : storeBizDtoList) {
            Integer storeId = storeBizDto.getStoreId();
            Integer dealerId = storeBizDto.getDealerId();

            StoreDetailDto storeDetailDto = storeDetailDtoMap.get(storeId);
            Convert.toStoreBizDto(storeBizDto, storeDetailDto);

            DealerDto dealerDto = dealerDtoMap.get(dealerId);
            if (dealerDto != null) {
                storeBizDto.setDealerStr(dealerDto.getShortName());
            }

            if (fenceCountMap != null && fenceCountMap.size() > 0) {
                Integer fenceCount = fenceCountMap.get(storeId);
                if (null == fenceCount) {
                    fenceCount = 0;
                }
                storeBizDto.setFenceCount(fenceCount);
            }else{
                storeBizDto.setFenceCount(0);
            }
        }
        return storeBizDtoList;
    }

    /**
     * 编辑门店信息
     *
     * @param storeBizModifyDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyStore(StoreBizModifyDto storeBizModifyDto) throws Exception {
        Assert.notNull(storeBizModifyDto, "编辑门店信息失败");

        StoreModifyDto storeModifyDto = Convert.toStore(storeBizModifyDto);
        Boolean storeBoolean = storeService.modifyStore(storeModifyDto);
        if (!storeBoolean) {
            return false;
        }

        StoreDetailModifyDto storeDetailModifyDto = Convert.toStoreDetail(storeBizModifyDto);
        Boolean storeDetailBoolean = storeDetailService.modifyStoreDetail(storeDetailModifyDto);
        if (!storeDetailBoolean) {
            return false;
        }

        String cpus = storeBizModifyDto.getCpus();
        Integer storeId = storeBizModifyDto.getStoreId();
        createOrModifyStoreDevice(StoreDeviceOptTypeEnum.MODIFY.getValue(), storeId, cpus);

        return true;
    }

    /**
     * 添加门店信息
     *
     * @param storeBizCreateDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Integer createStore(StoreBizCreateDto storeBizCreateDto) throws Exception {
        Assert.notNull(storeBizCreateDto, "添加门店信息失败");

        LocalDateTime nowTime = DateUtil.convertDateToLDT(new Date());

        StoreCreateDto storeCreateDto = Convert.toStore(storeBizCreateDto);
        storeCreateDto.setApplyTime(nowTime);
        Integer storeId = storeService.createStore(storeCreateDto);
        Assert.notNull(storeId, "添加门店信息失败");

        StoreDetailCreateDto storeDetailCreateDto = Convert.toStoreDetail(storeBizCreateDto);
        storeDetailCreateDto.setStoreId(storeId);
        Integer storeDetail = storeDetailService.createStoreDetail(storeDetailCreateDto);
        Assert.notNull(storeDetail, "添加门店信息失败");

        String cpus = storeBizCreateDto.getCpus();
        createOrModifyStoreDevice(StoreDeviceOptTypeEnum.CREATE.getValue(), storeId, cpus);

        return storeId;
    }


    /**
     * 添加或删除门店设备
     *
     * @param optType
     * @param storeId
     * @param cpus
     * @return
     * @throws Exception
     */
    private Boolean createOrModifyStoreDevice(int optType, Integer storeId, String cpus) throws Exception {
        if (StoreDeviceOptTypeEnum.CREATE.getValue() == optType && StringUtils.isBlank(cpus)) {
            return true;
        } else if (StoreDeviceOptTypeEnum.MODIFY.getValue() == optType && StringUtils.isBlank(cpus)) {
            List<Integer> oldDeviceIdList = storeDeviceService.getDeviceIdByStoreId(storeId);
            if (oldDeviceIdList != null && oldDeviceIdList.size() > 0) {
                return storeDeviceService.deleteStoreDeviceByStoreId(storeId);
            }
            return true;
        }
        cpus.replace("，", ",").replace(" ", "");
        List<String> cpuList = Arrays.asList(cpus.split(","));
        if (null == cpuList || cpuList.size() == 0) {
            throw new IllegalArgumentException("请输入正确的CPU号");
        }
        List<Integer> deviceIdList = new ArrayList<>();
        for (String cpu : cpuList) {
            Integer deviceId = deviceService.getDeviceIdByCpu(cpu);
            if (null == deviceId) {
                throw new IllegalArgumentException("CPU：" + cpu + "不存在，请输入正确的CPU号");
            }
            deviceIdList.add(deviceId);
        }

        List<Integer> storeDeviceList = storeDeviceService.getStoreDeviceByDeviceIds(storeId, deviceIdList);
        if (storeDeviceList != null && storeDeviceList.size() > 0) {
            DeviceDto deviceDto = deviceService.getDeviceById(storeDeviceList.get(0));
            throw new IllegalArgumentException("CPU：" + deviceDto.getCpu() + "已被绑定，请输入未绑定的CPU号");
        }
        createOrDeleteStoreDevice(storeId, deviceIdList);
        return true;
    }


    /**
     * 添加或删除门店设备
     *
     * @param storeId
     * @param deviceIdList
     * @return
     * @throws Exception
     */
    private void createOrDeleteStoreDevice(Integer storeId, List<Integer> deviceIdList) throws Exception {
        List<Integer> oldDeviceIdList = storeDeviceService.getDeviceIdByStoreId(storeId);
        if (null == oldDeviceIdList || oldDeviceIdList.size() == 0) {
            List<StoreDeviceDto> addList = new ArrayList<>();
            for (Integer deviceId : deviceIdList) {
                StoreDeviceDto storeDeviceDto = new StoreDeviceDto();
                storeDeviceDto.setStoreId(storeId);
                storeDeviceDto.setDeviceId(deviceId);
                addList.add(storeDeviceDto);
            }
            storeDeviceService.createStoreDeviceBatch(addList);
        } else {
            List<StoreDeviceDto> addList = new ArrayList<>();
            for (Integer deviceId : deviceIdList) {
                StoreDeviceDto storeDeviceDto = new StoreDeviceDto();
                storeDeviceDto.setStoreId(storeId);
                storeDeviceDto.setDeviceId(deviceId);
                addList.add(storeDeviceDto);
            }
            storeDeviceService.deleteStoreDeviceByStoreId(storeId);

            if (addList != null && addList.size() > 0) {
                storeDeviceService.createStoreDeviceBatch(addList);
            }
        }
    }

    /**
     * 门店审核
     *
     * @param storeId
     * @param verifyStatus
     * @param rejectReason
     * @param remark
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyStoreVerifyStatus(Integer storeId, Integer verifyStatus,
                                           String rejectReason, String remark) throws Exception {
        Assert.notNull(storeId, "门店审核失败");
        Assert.notNull(verifyStatus, "门店审核失败");

        StoreDto storeDto = storeService.getStoreById(storeId);
        Assert.notNull(storeDto, "门店不存在");

        Boolean verifyStatusBoolean = storeService.modifyVerifyStatus(storeId, verifyStatus, rejectReason, remark);
        if (verifyStatusBoolean && StoreVerifyStatusEnum.VERIFY_PASS.getValue() == verifyStatus) {
            return storeService.modifyStoreStatusByStoreId(storeId, StoreStatusEnum.OPEN.getValue(), null);
        }
        return true;
    }

    /**
     * 修改门店状态
     *
     * @param storeId
     * @param status
     * @param statusModifyType
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyStoreStatus(Integer storeId, Integer status, Integer statusModifyType) throws Exception {
        Assert.notNull(storeId, "编辑门店营业状态失败");
        Assert.notNull(status, "编辑门店营业状态失败");

        StoreDto storeDto = storeService.getStoreById(storeId);
        Assert.notNull(storeDto, "门店不存在");

        Integer oldStatus = storeDto.getStatus();
        if (StoreStatusEnum.SUSPENSION.getValue() == status && StoreStatusEnum.OPEN.getValue() != oldStatus) {
            throw new IllegalArgumentException("暂停营业失败");
        }
        if (StoreStatusEnum.OPEN.getValue() == status && StoreStatusEnum.SUSPENSION.getValue() != oldStatus) {
            throw new IllegalArgumentException("重新营业失败");
        }

        if (StoreStatusEnum.SUSPENSION.getValue() == status) {
            return storeService.modifyStoreStatusByStoreId(storeId, status, statusModifyType);
        }
        if (StoreStatusEnum.OPEN.getValue() == status) {
            checkStoreRequired(storeDto);
            Integer oldStatusModifyType = storeDto.getStatusModifyType();
            if (oldStatusModifyType != null && StoreStatusModifyTypeEnum.OP.getValue() == oldStatusModifyType) {
                return storeService.modifyVerifyStatus(storeId, StoreVerifyStatusEnum.UN_VERIFY.getValue(), null, null);
            } else if (oldStatusModifyType != null && StoreStatusModifyTypeEnum.DEALER.getValue() == oldStatusModifyType) {
                return storeService.modifyStoreStatusByStoreId(storeId, status, statusModifyType);
            }
        }

        return false;
    }

    /**
     * 门店校验
     *
     * @param storeDto
     * @throws Exception
     */
    private void checkStoreRequired(StoreDto storeDto) throws Exception {
        Integer storeId = storeDto.getStoreId();
        StoreDetailDto storeDetailDto = storeDetailService.getStoreDetailById(storeId);

        String shortName = storeDto.getShortName();
        String fullName = storeDto.getFullName();
        Boolean isFours = storeDto.getIsFours();
        Integer brandId = storeDto.getBrandId();
        String responsibleName = storeDetailDto.getResponsibleName();
        String responsiblePhone = storeDetailDto.getResponsiblePhone();
        Boolean isDeliver = storeDto.getIsDeliver();
        Boolean isSale = storeDto.getIsSale();
        Integer regionId = storeDto.getRegionId();
        String address = storeDetailDto.getAddress();
        String longitude = storeDetailDto.getLongitude();
        String dimension = storeDetailDto.getDimension();

        if (StringUtils.isBlank(shortName)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(fullName)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (null == isFours) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (isFours && null == brandId) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(responsibleName)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(responsiblePhone)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (null == isDeliver && null == isSale) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (null == regionId) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(address)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(longitude)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
        if (StringUtils.isBlank(dimension)) {
            throw new IllegalArgumentException("门店信息不全，请补全信息后，再操作重新营业");
        }
    }


    /**
     * 获取门店详情
     *
     * @param storeId
     * @return
     * @throws Exception
     */
    @Override
    public StoreInfoBizDto getStoreInfo(Integer storeId) throws Exception {
        Assert.notNull(storeId, "获取门店详情失败");
        StoreDto storeDto = storeService.getStoreById(storeId);
        if (null == storeDto) {
            return null;
        }
        StoreDetailDto storeDetailDto = storeDetailService.getStoreDetailById(storeId);
        StoreInfoBizDto storeInfoBizDto = Convert.toStoreInfo(storeDto);
        Convert.toStoreInfo(storeInfoBizDto, storeDetailDto);

        String cpus = getCpus(storeId);
        storeInfoBizDto.setCpus(cpus);
        Integer dealerId = storeInfoBizDto.getDealerId();
        if (dealerId == null) {
            return storeInfoBizDto;
        }

        DealerDto dealerDto = dealerService.getDealerById(dealerId);
        if (dealerDto == null) {
            return storeInfoBizDto;
        }

        String shortName = dealerDto.getShortName();
        storeInfoBizDto.setDealerStr(shortName);
        return storeInfoBizDto;
    }

    /**
     * 获取cpu
     *
     * @param storeId
     * @return
     * @throws Exception
     */
    private String getCpus(Integer storeId) throws Exception {

        List<Integer> deviceIdList = storeDeviceService.getDeviceIdByStoreId(storeId);
        if (null == deviceIdList || deviceIdList.size() < 1) {
            return null;
        }
        List<DeviceDto> deviceDtoList = deviceService.getDeviceListByIds(deviceIdList);
        if (null == deviceDtoList || deviceDtoList.size() < 1) {
            return null;
        }
        StringBuilder cpus = new StringBuilder();
        for (int i = 0; i < deviceDtoList.size(); i++) {
            DeviceDto deviceDto = deviceDtoList.get(i);
            String cpu = deviceDto.getCpu();
            if (StringUtils.isBlank(cpu)) {
                continue;
            }
            cpus.append(cpu);
            if (i < deviceDtoList.size() - 1) {
                cpus.append(",");
            }
        }
        return cpus.toString();
    }

    /**
     * 通过id获取经销商门店名称
     *
     * @param storeId
     * @return
     * @throws Exception
     */
    @Override
    public DealerStoreInfoBizDto getDealerStoreInfo(Integer storeId) throws Exception {
        StoreDto storeDto = storeService.getStoreById(storeId);
        if (null == storeDto) {
            return null;
        }
        DealerStoreInfoBizDto dealerStoreInfoBizDto = Convert.toDealerStoreInfoBizDto(storeDto);

        Integer dealerId = storeDto.getDealerId();
        if (dealerId != null) {
            DealerDto dealerDto = dealerService.getDealerById(dealerId);
            Convert.toDealerStoreInfoBizDto(dealerStoreInfoBizDto, dealerDto);
        }
        return dealerStoreInfoBizDto;
    }

    /**
     * 通过门店id获取门店和经销商名称集合
     *
     * @param storeIdList
     * @return
     */
    @Override
    public Map<Integer, DealerStoreInfoBizDto> getDealerStoreInfoMap(List<Integer> storeIdList) throws Exception {
        if (null == storeIdList || storeIdList.size() <= 0) {
            return null;
        }

        List<StoreDto> storeList = storeService.getStoreListByIds(storeIdList);
        if (null == storeList || storeList.size() <= 0) {
            return null;
        }

        List<DealerStoreInfoBizDto> dealerStoreInfoBizDtoList = Convert.toDealerStoreInfoBizDtoList(storeList);
        List<Integer> dealerIdList = new ArrayList<Integer>();
        for (DealerStoreInfoBizDto dealerStoreInfoBizDto : dealerStoreInfoBizDtoList) {
            dealerIdList.add(dealerStoreInfoBizDto.getDealerId());
        }

        if (dealerIdList != null && dealerIdList.size() > 0) {
            Map<Integer, DealerDto> dealerMap = dealerService.getDealerMapByIds(dealerIdList);
            Convert.toDealerStoreInfoBizDtoList(dealerStoreInfoBizDtoList, dealerMap);
        }
        return Convert.toDealerStoreInfoBizDtoMap(dealerStoreInfoBizDtoList);
    }
    
    
    /**
     * 通过门店id获取门店和经销商名称集合
     *
     * @param storeIdList
     * @param status
     * @param notStoreIdList
     * @return
     * @throws Exception
     */
    @Override
    public List<DealerStoreInfoBizDto> getDealerStoreInfoBystoreIdList(List<Integer> storeIdList, Integer status,List<Integer> notStoreIdList) throws Exception {
	    if (null == storeIdList || storeIdList.size() <= 0) {
	        return null;
	    }
	
	    List<StoreDto> storeList = storeService.getStoreListByIdsAndStatus(storeIdList,status,notStoreIdList);
	    if (null == storeList || storeList.size() <= 0) {
	        return null;
	    }
	
	    List<DealerStoreInfoBizDto> dealerStoreInfoBizDtoList = Convert.toDealerStoreInfoBizDtoList(storeList);
	    List<Integer> dealerIdList = new ArrayList<Integer>();
	    for (DealerStoreInfoBizDto dealerStoreInfoBizDto : dealerStoreInfoBizDtoList) {
	        dealerIdList.add(dealerStoreInfoBizDto.getDealerId());
	    }
	
	    if (dealerIdList != null && dealerIdList.size() > 0) {
	        Map<Integer, DealerDto> dealerMap = dealerService.getDealerMapByIds(dealerIdList);
	        Convert.toDealerStoreInfoBizDtoList(dealerStoreInfoBizDtoList, dealerMap);
	    }
    	return dealerStoreInfoBizDtoList;
    }


    /**
     * 通过城市获取门店列表
     *
     * @param map key：regionId Integer 区域ID
     * @return
     * @throws Exception
     */
    @Override
    public List<StoreInfoBizDto> getStoreInfoList(Map<String, Object> map) throws Exception {
        List<StoreDto> storeDtoList = storeService.getStoreList(map);
        if (null == storeDtoList || storeDtoList.size() < 1) {
            return null;
        }

        List<Integer> storeIdList = new ArrayList<>();
        for (StoreDto storeDto : storeDtoList) {
            storeIdList.add(storeDto.getStoreId());
        }
        Map<Integer, StoreDetailDto> storeDetailDtoMap = storeDetailService.getStoreDetailMapByIds(storeIdList);
        List<StoreInfoBizDto> returnList = getReturnList(storeDtoList, storeDetailDtoMap);
        getDistance(map, returnList);

        return returnList;
    }


    /**
     * 获取返回list
     *
     * @param storeDtoList
     * @param storeDetailDtoMap
     * @return
     * @throws Exception
     */
    private List<StoreInfoBizDto> getReturnList(List<StoreDto> storeDtoList, Map<Integer, StoreDetailDto> storeDetailDtoMap) throws Exception {
        List<StoreInfoBizDto> storeInfoBizDtoList = Convert.toStoreInfoBizDtoList(storeDtoList);
        for (StoreInfoBizDto storeInfoBizDto : storeInfoBizDtoList) {
            Integer storeId = storeInfoBizDto.getStoreId();

            StoreDetailDto storeDetailDto = storeDetailDtoMap.get(storeId);
            Convert.toStoreInfoBizDto(storeDetailDto, storeInfoBizDto);

            String contactPhone = storeInfoBizDto.getContactPhone();
            if (StringUtils.isBlank(contactPhone)) {
                storeInfoBizDto.setContactPhone(STORE_CONTACT_PHONE);
            }
        }
        return storeInfoBizDtoList;
    }

    /**
     * 获取距离
     *
     * @param map
     * @param returnList
     */
    private void getDistance(Map<String, Object> map, List<StoreInfoBizDto> returnList) {
        Object objLongitude = map.get("longitude");
        Object objDimension = map.get("dimension");
        if (null == objLongitude || null == objDimension) {
            returnList.sort(Comparator.comparing(StoreInfoBizDto::getStatus));
            return;
        }

        for (StoreInfoBizDto storeInfoBizDto : returnList) {
            String longitude = storeInfoBizDto.getLongitude();
            String dimension = storeInfoBizDto.getDimension();
            double longitudeDou = Double.parseDouble(longitude);
            double dimensionDou = Double.parseDouble(dimension);

            Double locationLongitude = ObjectCastUtil.castDouble(objLongitude);
            Double locationDimension = ObjectCastUtil.castDouble(objDimension);
            double distance = LocationUtils.getDistance(locationLongitude, locationDimension, longitudeDou, dimensionDou);
            storeInfoBizDto.setDistanceSort(distance);
            storeInfoBizDto.setDistance(String.valueOf(distance));
        }

        returnList.sort(Comparator.comparing(StoreInfoBizDto::getStatus).thenComparing(StoreInfoBizDto::getDistanceSort));
        for (StoreInfoBizDto storeInfoBizDto : returnList) {
            String distance = storeInfoBizDto.getDistance();
            storeInfoBizDto.setDistance(Convert.MToKm(distance));
        }
    }

    /**
     * 查询门店基本信息
     *
     * @param cpu 设备cpu号
     * @return
     * @throws Exception
     */
    @Override
    public StoreBaseBizDto getStoreBaseByCpu(String cpu) throws Exception {
        StoreBaseBizDto result = null;
        // 根据cpu查询设备id
        Integer deviceId = deviceService.getDeviceIdByCpu(cpu);
        if (deviceId == null) {
            return result;
        }
        // 根据设备id查询门店id
        Integer storeId = storeDeviceService.getStoreIdByDevice(deviceId);
        if (storeId == null) {
            return result;
        }

        return getStoreBaseById(storeId);
    }

    /**
     * 查询门店基本信息
     *
     * @param storeId 设备cpu号
     * @return
     * @throws Exception
     */
    @Override
    public StoreBaseBizDto getStoreBaseById(Integer storeId) throws Exception {
        return storeId == null ? null : Convert.toStoreBaseBizDto(storeService.getStoreById(storeId));
    }

    /**
     * 查询门店详情信息
     *
     * @param cpu 设备cpu号
     * @return
     * @throws Exception
     */
    @Override
    public StoreBizDto getStoreDetailsByCpu(String cpu) throws Exception {
        // 根据cpu查询设备id
        Integer deviceId = deviceService.getDeviceIdByCpu(cpu);
        if (deviceId == null) {
            return null;
        }
        // 根据设备id查询门店id
        Integer storeId = storeDeviceService.getStoreIdByDevice(deviceId);
        if (storeId == null) {
            return null;
        }
        return getStoreDetailsById(storeId);
    }

    /**
     * 查询门店详情信息
     *
     * @param storeId 门店id
     * @return
     * @throws Exception
     */
    @Override
    public StoreBizDto getStoreDetailsById(Integer storeId) throws Exception {
        StoreBizDto result = null;
        StoreDto storeDto = storeService.getStoreById(storeId);
        result = Convert.toStoreBizDto(storeDto);
        // 查询详情
        StoreDetailDto storeDetailDto = storeDetailService.getStoreDetailById(storeId);
        return Convert.toStoreBizDto(result, storeDetailDto);
    }

    /**
     * 门店名称模糊查询
     *
     * @param map key:shortName String 门店名称
     *            key:storeStatus Integer 门店营业状态（null：所有门店，1：门店营业中）
     *            key:dealerId Integer 经销商id
     *            key:dealerStatus Integer 经销商营业状态（null：所有门店，1：经销商营业中）
     *            key:dealerType Integer 经销商类型(null:所有，1:直销，2：分销)
     *            key:isShow Integer 删除是否显示(null:所有，0:否，1：是)
     * @return
     */
    @Override
    public List<StoreBizDto> getStoreByShortNameFuzzy(Map<String, Object> map) throws Exception {
        Integer dealerId = ObjectCastUtil.castInteger(map.get("dealerId"));
        Integer dealerStatus = ObjectCastUtil.castInteger(map.get("dealerStatus"));
        Integer dealerType = ObjectCastUtil.castInteger(map.get("dealerType"));
        String shortName = ObjectCastUtil.castString(map.get("shortName"));
        Integer storeStatus = ObjectCastUtil.castInteger(map.get("storeStatus"));
        Integer isShow = ObjectCastUtil.castInteger(map.get("isShow"));

        List<Integer> dealerIdList = getDealerIdList(dealerId, dealerStatus, dealerType);
        List<StoreDto> storeDtoList = storeService.getStoreByShortNameFuzzy(shortName, storeStatus, isShow, dealerIdList);
        return Convert.toStoreBizDtoList(storeDtoList);
    }

    private List<Integer> getDealerIdList(Integer dealerId, Integer dealerStatus, Integer dealerType) throws Exception {
        if (dealerId == null && dealerStatus == null && dealerType == null) {
            return null;
        }

        List<DealerDto> dealerDtoList = dealerService.getAllDealerList(dealerStatus, dealerType, dealerId);
        if (dealerDtoList == null || dealerDtoList.size() < 1) {
            return null;
        }
        return dealerDtoList.stream().map(DealerDto::getDealerId).collect(Collectors.toList());
    }

}